package com.lvmama.autoconfig;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.annotation.MapperScannerRegistrar;
import org.mybatis.spring.mapper.ClassPathMapperScanner;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@Component
public class CustomerMapperScannerRegister extends MapperScannerRegistrar implements EnvironmentAware{
	/**
	* @author zhoutianqi
	* @className CustomerMapperScannerRegister.java
	* @date 2017年8月31日 下午1:00:24
	* @description 
	*/
	private ResourceLoader resourceLoader;
	private Environment env;

	  /**
	   * {@inheritDoc}
	   */
	  @Override
	  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

	    AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(CustomerMapperScanner.class.getName()));
	    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

	    // this check is needed in Spring 3.1
	    if (resourceLoader != null) {
	      scanner.setResourceLoader(resourceLoader);
	    }

	    Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
	    if (!Annotation.class.equals(annotationClass)) {
	      scanner.setAnnotationClass(annotationClass);
	    }

	    Class<?> markerInterface = annoAttrs.getClass("markerInterface");
	    if (!Class.class.equals(markerInterface)) {
	      scanner.setMarkerInterface(markerInterface);
	    }

	    Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
	    if (!BeanNameGenerator.class.equals(generatorClass)) {
	      scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
	    }

	    Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
	    if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
	      scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
	    }

	    scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
	    scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));

	    List<String> basePackages = new ArrayList<String>();
	    for (String pkg : annoAttrs.getStringArray("value")) {
	      if (StringUtils.hasText(pkg)) {
	        basePackages.add(parsePlaceHolder(pkg));
	      }
	    }
	    for (String pkg : annoAttrs.getStringArray("basePackages")) {
	      if (StringUtils.hasText(pkg)) {
	        basePackages.add(parsePlaceHolder(pkg));
	      }
	    }
	    for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
	      basePackages.add(ClassUtils.getPackageName(clazz));
	    }
	    scanner.registerFilters();
	    scanner.doScan(StringUtils.toStringArray(basePackages));
	  }
	@Override
	  public void setResourceLoader(ResourceLoader resourceLoader) {
	    this.resourceLoader = resourceLoader;
	  }
	
	private String parsePlaceHolder(String pro) {
        if (pro != null && pro.contains(PropertySourcesPlaceholderConfigurer.DEFAULT_PLACEHOLDER_PREFIX)) {
            String value = env.getProperty(pro.substring(2, pro.length() - 1));
/*
            if (logger.isDebugEnabled()) {
                logger.debug("find placeholder value " + value + " for key " + pro);
            }
*/
            if (null == value) {
                throw new IllegalArgumentException("property " + pro + " can not find!!!");
            }
            return value;
        }
        return pro;
    }
	@Override
	public void setEnvironment(Environment env) {
		this.env=env;
	}
}
